regs->eax = info->func(info->data);
v->arch.schedule_tail = info->saved_schedule_tail;
- v->cpu_affinity = info->saved_affinity;
+ v->arch.continue_info = NULL;
xfree(info);
- v->arch.continue_info = NULL;
vcpu_set_affinity(v, &v->cpu_affinity);
schedule_tail(v);
struct vcpu *v = current;
struct migrate_info *info;
cpumask_t mask = cpumask_of_cpu(cpu);
+ int rc;
if ( cpu == smp_processor_id() )
return func(data);
info->func = func;
info->data = data;
info->saved_schedule_tail = v->arch.schedule_tail;
- v->arch.schedule_tail = continue_hypercall_on_cpu_helper;
-
info->saved_affinity = v->cpu_affinity;
+
+ v->arch.schedule_tail = continue_hypercall_on_cpu_helper;
v->arch.continue_info = info;
- vcpu_set_affinity(v, &mask);
+ rc = vcpu_set_affinity(v, &mask);
+ if ( rc )
+ {
+ v->arch.schedule_tail = info->saved_schedule_tail;
+ v->arch.continue_info = NULL;
+ xfree(info);
+ return rc;
+ }
/* Dummy return value will be overwritten by new schedule_tail. */
BUG_ON(!test_bit(SCHEDULE_SOFTIRQ, &softirq_pending(smp_processor_id())));
extern spinlock_t xenpf_lock;
#endif
+static long cpu_frequency_change_helper(void *data)
+{
+ return cpu_frequency_change(*(uint64_t *)data);
+}
+
ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
{
ret_t ret = 0;
ret = acpi_enter_sleep(&op->u.enter_acpi_sleep);
break;
+ case XENPF_change_freq:
+ ret = -EINVAL;
+ if ( op->u.change_freq.flags != 0 )
+ break;
+ ret = continue_hypercall_on_cpu(op->u.change_freq.cpu,
+ cpu_frequency_change_helper,
+ &op->u.change_freq.freq);
+ break;
+
default:
ret = -ENOSYS;
break;
spin_unlock(&wc_lock);
}
+int cpu_frequency_change(u64 freq)
+{
+ struct cpu_time *t = &this_cpu(cpu_time);
+ u64 curr_tsc;
+
+ local_irq_disable();
+ set_time_scale(&t->tsc_scale, freq);
+ rdtscll(curr_tsc);
+ t->local_tsc_stamp = curr_tsc;
+ t->stime_local_stamp = get_s_time();
+ t->stime_master_stamp = read_platform_stime();
+ local_irq_enable();
+
+ /* A full epoch should pass before we check for deviation. */
+ set_timer(&t->calibration_timer, NOW() + EPOCH);
+ if ( smp_processor_id() == 0 )
+ platform_time_calibration();
+
+ return 0;
+}
+
/* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
{
error_factor, calibration_mul_frac, tsc_shift);
#endif
- /* Record new timestamp information. */
+ /* Record new timestamp information, atomically w.r.t. interrupts. */
+ local_irq_disable();
t->tsc_scale.mul_frac = calibration_mul_frac;
t->tsc_scale.shift = tsc_shift;
t->local_tsc_stamp = curr_tsc;
t->stime_local_stamp = curr_local_stime;
t->stime_master_stamp = curr_master_stime;
+ local_irq_enable();
update_vcpu_system_time(current);
v->arch.guest_context.gs_base_user = res;
break;
#endif
+ case MSR_K8_FIDVID_STATUS:
+ case MSR_K8_FIDVID_CTL:
+ if ( (cpufreq_controller != FREQCTL_dom0_kernel) ||
+ (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) ||
+ wrmsr_safe(regs->ecx, eax, edx) )
+ goto fail;
+ break;
default:
if ( wrmsr_hypervisor_regs(regs->ecx, eax, edx) )
break;
-
if ( (rdmsr_safe(regs->ecx, l, h) != 0) ||
(eax != l) || (edx != h) )
gdprintk(XENLOG_WARNING, "Domain attempted WRMSR %p from "
regs->edx = v->arch.guest_context.gs_base_user >> 32;
break;
#endif
+ case MSR_K8_FIDVID_CTL:
+ case MSR_K8_FIDVID_STATUS:
+ if ( (cpufreq_controller != FREQCTL_dom0_kernel) ||
+ (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) ||
+ rdmsr_safe(regs->ecx, regs->eax, regs->edx) )
+ goto fail;
+ break;
case MSR_EFER:
if ( rdmsr_safe(regs->ecx, regs->eax, regs->edx) )
goto fail;
static unsigned int opt_dom0_vcpus_pin;
boolean_param("dom0_vcpus_pin", opt_dom0_vcpus_pin);
+enum cpufreq_controller cpufreq_controller;
+static void __init setup_cpufreq_option(char *str)
+{
+ if ( !strcmp(str, "dom0-kernel") )
+ {
+ cpufreq_controller = FREQCTL_dom0_kernel;
+ opt_dom0_vcpus_pin = 1;
+ }
+}
+custom_param("cpufreq", setup_cpufreq_option);
+
#define TIME_SLOP (s32)MICROSECS(50) /* allow time to slip a bit */
/* Various timer handlers. */
#define MSR_K8_VM_CR 0xC0010114
#define MSR_K8_VM_HSAVE_PA 0xC0010117
+#define MSR_K8_FIDVID_CTL 0xC0010041
+#define MSR_K8_FIDVID_STATUS 0xC0010042
+
/* MSR_K8_VM_CR bits: */
#define _K8_VMCR_SVME_DISABLE 4
#define K8_VMCR_SVME_DISABLE (1 << _K8_VMCR_SVME_DISABLE)
struct ioreq;
int dom0_pit_access(struct ioreq *ioreq);
+int cpu_frequency_change(u64 freq);
+
#endif /* __X86_TIME_H__ */
typedef struct xenpf_enter_acpi_sleep xenpf_enter_acpi_sleep_t;
DEFINE_XEN_GUEST_HANDLE(xenpf_enter_acpi_sleep_t);
+#define XENPF_change_freq 52
+struct xenpf_change_freq {
+ /* IN variables */
+ uint32_t flags; /* Must be zero. */
+ uint32_t cpu; /* Physical cpu. */
+ uint64_t freq; /* New frequency (Hz). */
+};
+typedef struct xenpf_change_freq xenpf_change_freq_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_change_freq_t);
+
struct xen_platform_op {
uint32_t cmd;
uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
struct xenpf_platform_quirk platform_quirk;
struct xenpf_firmware_info firmware_info;
struct xenpf_enter_acpi_sleep enter_acpi_sleep;
+ struct xenpf_change_freq change_freq;
uint8_t pad[128];
} u;
};
#define is_hvm_domain(d) ((d)->is_hvm)
#define is_hvm_vcpu(v) (is_hvm_domain(v->domain))
+extern enum cpufreq_controller {
+ FREQCTL_none, FREQCTL_dom0_kernel
+} cpufreq_controller;
+
#endif /* __SCHED_H__ */
/*
-/****************************************************************************
- * (C) 2002 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
- *
- * File: time.h
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes:
- *
- * Date: Nov 2002
+/******************************************************************************
+ * time.h
*
- * Environment: Xen Hypervisor
- * Description: This file provides a one stop shop for all time related
- * issues within the hypervisor.
- *
- * The Hypervisor provides the following notions of time:
- * Cycle Counter Time, System Time, Wall Clock Time, and
- * Domain Virtual Time.
- *
- ****************************************************************************
- * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
- ****************************************************************************
+ * Copyright (c) 2002-2003 Rolf Neugebauer
+ * Copyright (c) 2002-2005 K A Fraser
*/
-
-
#ifndef __XEN_TIME_H__
#define __XEN_TIME_H__